#include <iostream>
#include <string>
#include <unordered_map>
// 枚举类
enum class Color { Red, Green, Blue };  // 枚举值被限定在 Color 命名空间内

// 枚举类可以指定底层类型 NOTE: 注意是底层类型，不能是非整数类型如std::string
enum class Fruit : int { Apple, Green, Banana, Cherry };

enum class PrimitiveTypeTag : char { INT = 'i', DOUBLE = 'd', CHAR = 'c', BOOLEAN = 'b' };

//测试两个问题：
//             1. enum class对string的支持
//             2. enum class里用#define宏
enum class PrimeTest : char {
#define PT_PROCESS(X, Y) X,
#include "PrimType.inc"
#undef PT_PROCESS
};

//测试一个问题：
//            1. enum class类和map的键值对数据结构结合使用
enum class PrimitiveTypeTagNew : char { Int, Float, String };

enum class Day {
    Sunday,                 // 默认值为0
    Monday,                 // 默认值为1
    Tuesday,                // 默认值为2
    Wednesday = 10,         // 指定值为10
    Thursday,               // 值为11，因为前一个成员值为10
    Friday = Thursday + 1,  // 值为12
    Saturday                // 值为13，因为前一个成员值为12
};

// int main() {
//     Day today = Day::Wednesday;

//     if (today == Day::Wednesday) {
//         std::cout << "Today is Wednesday." << std::endl;
//     }

//     std::cout << "Saturday is " << static_cast<int>(Day::Saturday) << "th day of the week." <<
//     std::endl;

//     return 0;
// }

int main() {
    // 作用域限定，避免命名冲突
    Color color = Color::Green;
    Fruit fruit = Fruit::Green;

    // 防止不必要的隐式转换
    // int colorValue = color; // 错误，无法隐式转换为整数
    // int fruitValue = fruit; // 错误，无法隐式转换为整数

    // 显式转换
    int colorValue = static_cast<int>(color);
    int fruitValue = static_cast<int>(fruit);

    // 输出结果
    std::cout << "Color value: " << colorValue << std::endl;
    std::cout << "Fruit value: " << fruitValue << std::endl;

    Day today = Day::Wednesday;

    if (today == Day::Wednesday) {
        std::cout << "Today is Wednesday." << std::endl;
    }

    std::cout << "Saturday is " << static_cast<int>(Day::Saturday) << "th day of the week."
              << std::endl;

    PrimitiveTypeTag type = PrimitiveTypeTag::DOUBLE;

    switch (type) {
        case PrimitiveTypeTag::INT:
            std::cout << "INT" << std::endl;
            break;
        case PrimitiveTypeTag::DOUBLE:
            std::cout << static_cast<char>(PrimitiveTypeTag::DOUBLE) << std::endl;
            break;
        case PrimitiveTypeTag::CHAR:
            std::cout << "CHAR" << std::endl;
            break;
        case PrimitiveTypeTag::BOOLEAN:
            std::cout << "BOOLEAN" << std::endl;
            break;
    }

    std::cout << static_cast<char>(PrimeTest::i8) << std::endl;
    std::cout << static_cast<char>(PrimeTest::i16) << std::endl;

    // unordered_map 嵌套enum class
    std::unordered_map<PrimitiveTypeTagNew, std::string> typeToString = {
        {PrimitiveTypeTagNew::Int, "int"},
        {PrimitiveTypeTagNew::Float, "float"},
        {PrimitiveTypeTagNew::String, "string"}};
        
    PrimitiveTypeTagNew testtestset = PrimitiveTypeTagNew::Float;
    std::cout << "Test unordered map: " << typeToString[testtestset] << std::endl;

    // PrimitiveTypeTagNew RTTGet(PrimitiveTypeTagNew::Int);
    // RTTGet::value();
    return 0;
}
